Bug 1343453 - Backport fixes for upstream issues #317, #318, #332, and #335.

diff --git a/ipc/chromium/src/third_party/libevent/README.mozilla b/ipc/chromium/src/third_party/libevent/README.mozilla
--- a/ipc/chromium/src/third_party/libevent/README.mozilla
+++ b/ipc/chromium/src/third_party/libevent/README.mozilla
@@ -36,8 +36,11 @@ ipc/chromium/src/third_party/libevent/pa
   architecture (which does not provide deprecated syscalls).
 
 - "dont-use-issetugid-on-android.patch". This fixes the build on Android L
   preview.
 
 - "avoid-empty-sighandler.patch". This fixes some OS X crashes.
 
 - "android64_support.patch". This fixes Android 64-bit support.
+
+- "backport-upstream-fixes.patch". Backports a few upstream fixes from 2.1.x
+  to our in-tree copy of 2.0.21.
diff --git a/ipc/chromium/src/third_party/libevent/buffer.c b/ipc/chromium/src/third_party/libevent/buffer.c
--- a/ipc/chromium/src/third_party/libevent/buffer.c
+++ b/ipc/chromium/src/third_party/libevent/buffer.c
@@ -1539,17 +1539,21 @@ evbuffer_add(struct evbuffer *buf, const
 	int result = -1;
 
 	EVBUFFER_LOCK(buf);
 
 	if (buf->freeze_end) {
 		goto done;
 	}
 
-	chain = buf->last;
+	if (*buf->last_with_datap == NULL) {
+		chain = buf->last;
+	} else {
+		chain = *buf->last_with_datap;
+	}
 
 	/* If there are no chains allocated for this buffer, allocate one
 	 * big enough to hold all the data. */
 	if (chain == NULL) {
 		chain = evbuffer_chain_new(datlen);
 		if (!chain)
 			goto done;
 		evbuffer_chain_insert(buf, chain);
diff --git a/ipc/chromium/src/third_party/libevent/evdns.c b/ipc/chromium/src/third_party/libevent/evdns.c
--- a/ipc/chromium/src/third_party/libevent/evdns.c
+++ b/ipc/chromium/src/third_party/libevent/evdns.c
@@ -947,17 +947,16 @@ name_parse(u8 *packet, int length, int *
 	/* Normally, names are a series of length prefixed strings terminated */
 	/* with a length of 0 (the lengths are u8's < 63). */
 	/* However, the length can start with a pair of 1 bits and that */
 	/* means that the next 14 bits are a pointer within the current */
 	/* packet. */
 
 	for (;;) {
 		u8 label_len;
-		if (j >= length) return -1;
 		GET8(label_len);
 		if (!label_len) break;
 		if (label_len & 0xc0) {
 			u8 ptr_low;
 			GET8(ptr_low);
 			if (name_end < 0) name_end = j;
 			j = (((int)label_len & 0x3f) << 8) + ptr_low;
 			/* Make sure that the target offset is in-bounds. */
@@ -968,16 +967,17 @@ name_parse(u8 *packet, int length, int *
 			continue;
 		}
 		if (label_len > 63) return -1;
 		if (cp != name_out) {
 			if (cp + 1 >= end) return -1;
 			*cp++ = '.';
 		}
 		if (cp + label_len >= end) return -1;
+		if (j + label_len > length) return -1;
 		memcpy(cp, packet + j, label_len);
 		cp += label_len;
 		j += label_len;
 	}
 	if (cp >= end) return -1;
 	*cp = '\0';
 	if (name_end < 0)
 		*idx = j;
@@ -3102,19 +3102,22 @@ search_set_from_hostname(struct evdns_ba
 	if (!domainname) return;
 	search_postfix_add(base, domainname);
 }
 
 /* warning: returns malloced string */
 static char *
 search_make_new(const struct search_state *const state, int n, const char *const base_name) {
 	const size_t base_len = strlen(base_name);
-	const char need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1;
+	char need_to_append_dot;
 	struct search_domain *dom;
 
+	if (!base_len) return NULL;
+	need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1;
+
 	for (dom = state->head; dom; dom = dom->next) {
 		if (!n--) {
 			/* this is the postfix we want */
 			/* the actual postfix string is kept at the end of the structure */
 			const u8 *const postfix = ((u8 *) dom) + sizeof(struct search_domain);
 			const int postfix_len = dom->len;
 			char *const newname = (char *) mm_malloc(base_len + need_to_append_dot + postfix_len + 1);
 			if (!newname) return NULL;
diff --git a/ipc/chromium/src/third_party/libevent/evutil.c b/ipc/chromium/src/third_party/libevent/evutil.c
--- a/ipc/chromium/src/third_party/libevent/evutil.c
+++ b/ipc/chromium/src/third_party/libevent/evutil.c
@@ -1803,22 +1803,22 @@ evutil_parse_sockaddr_port(const char *i
 	 * ipv6
 	 * [ipv6]
 	 * ipv4:port
 	 * ipv4
 	 */
 
 	cp = strchr(ip_as_string, ':');
 	if (*ip_as_string == '[') {
-		int len;
+		size_t len;
 		if (!(cp = strchr(ip_as_string, ']'))) {
 			return -1;
 		}
-		len = (int) ( cp-(ip_as_string + 1) );
-		if (len > (int)sizeof(buf)-1) {
+		len = ( cp-(ip_as_string + 1) );
+		if (len > sizeof(buf)-1) {
 			return -1;
 		}
 		memcpy(buf, ip_as_string+1, len);
 		buf[len] = '\0';
 		addr_part = buf;
 		if (cp[1] == ':')
 			port_part = cp+2;
 		else
diff --git a/ipc/chromium/src/third_party/libevent/patches/backport-upstream-fixes.patch b/ipc/chromium/src/third_party/libevent/patches/backport-upstream-fixes.patch
new file mode 100644
--- /dev/null
+++ b/ipc/chromium/src/third_party/libevent/patches/backport-upstream-fixes.patch
@@ -0,0 +1,140 @@
+Bug 1343453 - Backport fixes for upstream issues #317, #318, #332, #335, and #340.
+
+diff --git a/ipc/chromium/src/third_party/libevent/buffer.c b/ipc/chromium/src/third_party/libevent/buffer.c
+--- a/ipc/chromium/src/third_party/libevent/buffer.c
++++ b/ipc/chromium/src/third_party/libevent/buffer.c
+@@ -1553,17 +1553,21 @@ evbuffer_add(struct evbuffer *buf, const
+ 	if (buf->freeze_end) {
+ 		goto done;
+ 	}
+ 	/* Prevent buf->total_len overflow */
+ 	if (datlen > EV_SIZE_MAX - buf->total_len) {
+ 		goto done;
+ 	}
+ 
+-	chain = buf->last;
++	if (*buf->last_with_datap == NULL) {
++		chain = buf->last;
++	} else {
++		chain = *buf->last_with_datap;
++	}
+ 
+ 	/* If there are no chains allocated for this buffer, allocate one
+ 	 * big enough to hold all the data. */
+ 	if (chain == NULL) {
+ 		chain = evbuffer_chain_new(datlen);
+ 		if (!chain)
+ 			goto done;
+ 		evbuffer_chain_insert(buf, chain);
+@@ -1795,18 +1799,17 @@ evbuffer_expand_singlechain(struct evbuf
+ 	 * it, use the next chunk after it, or   If we add a new chunk, we waste
+ 	 * CHAIN_SPACE_LEN(chain) bytes in the former last chunk.  If we
+ 	 * resize, we have to copy chain->off bytes.
+ 	 */
+ 
+ 	/* Would expanding this chunk be affordable and worthwhile? */
+ 	if (CHAIN_SPACE_LEN(chain) < chain->buffer_len / 8 ||
+ 	    chain->off > MAX_TO_COPY_IN_EXPAND ||
+-	    (datlen < EVBUFFER_CHAIN_MAX &&
+-		EVBUFFER_CHAIN_MAX - datlen >= chain->off)) {
++	    datlen >= (EVBUFFER_CHAIN_MAX - chain->off)) {
+ 		/* It's not worth resizing this chain. Can the next one be
+ 		 * used? */
+ 		if (chain->next && CHAIN_SPACE_LEN(chain->next) >= datlen) {
+ 			/* Yes, we can just use the next chain (which should
+ 			 * be empty. */
+ 			result = chain->next;
+ 			goto ok;
+ 		} else {
+diff --git a/ipc/chromium/src/third_party/libevent/evdns.c b/ipc/chromium/src/third_party/libevent/evdns.c
+--- a/ipc/chromium/src/third_party/libevent/evdns.c
++++ b/ipc/chromium/src/third_party/libevent/evdns.c
+@@ -955,17 +955,16 @@ name_parse(u8 *packet, int length, int *
+ 	/* Normally, names are a series of length prefixed strings terminated */
+ 	/* with a length of 0 (the lengths are u8's < 63). */
+ 	/* However, the length can start with a pair of 1 bits and that */
+ 	/* means that the next 14 bits are a pointer within the current */
+ 	/* packet. */
+ 
+ 	for (;;) {
+ 		u8 label_len;
+-		if (j >= length) return -1;
+ 		GET8(label_len);
+ 		if (!label_len) break;
+ 		if (label_len & 0xc0) {
+ 			u8 ptr_low;
+ 			GET8(ptr_low);
+ 			if (name_end < 0) name_end = j;
+ 			j = (((int)label_len & 0x3f) << 8) + ptr_low;
+ 			/* Make sure that the target offset is in-bounds. */
+@@ -976,16 +975,17 @@ name_parse(u8 *packet, int length, int *
+ 			continue;
+ 		}
+ 		if (label_len > 63) return -1;
+ 		if (cp != name_out) {
+ 			if (cp + 1 >= end) return -1;
+ 			*cp++ = '.';
+ 		}
+ 		if (cp + label_len >= end) return -1;
++		if (j + label_len > length) return -1;
+ 		memcpy(cp, packet + j, label_len);
+ 		cp += label_len;
+ 		j += label_len;
+ 	}
+ 	if (cp >= end) return -1;
+ 	*cp = '\0';
+ 	if (name_end < 0)
+ 		*idx = j;
+@@ -3117,19 +3117,22 @@ search_set_from_hostname(struct evdns_ba
+ 	if (!domainname) return;
+ 	search_postfix_add(base, domainname);
+ }
+ 
+ /* warning: returns malloced string */
+ static char *
+ search_make_new(const struct search_state *const state, int n, const char *const base_name) {
+ 	const size_t base_len = strlen(base_name);
+-	const char need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1;
++	char need_to_append_dot;
+ 	struct search_domain *dom;
+ 
++	if (!base_len) return NULL;
++	need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1;
++
+ 	for (dom = state->head; dom; dom = dom->next) {
+ 		if (!n--) {
+ 			/* this is the postfix we want */
+ 			/* the actual postfix string is kept at the end of the structure */
+ 			const u8 *const postfix = ((u8 *) dom) + sizeof(struct search_domain);
+ 			const int postfix_len = dom->len;
+ 			char *const newname = (char *) mm_malloc(base_len + need_to_append_dot + postfix_len + 1);
+ 			if (!newname) return NULL;
+diff --git a/ipc/chromium/src/third_party/libevent/evutil.c b/ipc/chromium/src/third_party/libevent/evutil.c
+--- a/ipc/chromium/src/third_party/libevent/evutil.c
++++ b/ipc/chromium/src/third_party/libevent/evutil.c
+@@ -1803,22 +1803,22 @@ evutil_parse_sockaddr_port(const char *i
+ 	 * ipv6
+ 	 * [ipv6]
+ 	 * ipv4:port
+ 	 * ipv4
+ 	 */
+ 
+ 	cp = strchr(ip_as_string, ':');
+ 	if (*ip_as_string == '[') {
+-		int len;
++		size_t len;
+ 		if (!(cp = strchr(ip_as_string, ']'))) {
+ 			return -1;
+ 		}
+-		len = (int) ( cp-(ip_as_string + 1) );
+-		if (len > (int)sizeof(buf)-1) {
++		len = ( cp-(ip_as_string + 1) );
++		if (len > sizeof(buf)-1) {
+ 			return -1;
+ 		}
+ 		memcpy(buf, ip_as_string+1, len);
+ 		buf[len] = '\0';
+ 		addr_part = buf;
+ 		if (cp[1] == ':')
+ 			port_part = cp+2;
+ 		else
